@file:JvmMultifileClass
@file:JvmName("ByteUtils")

package hos.kotlin

import java.security.MessageDigest

/**
 * <p>Title: ByteArrayExt </p>
 * <p>Description:  </p>
 * <p>Company: www.mapuni.com </p>
 *
 * @author : 蔡俊峰
 * @date : 2024-07-11 20:05
 * @version : 1.0
 */

private
const val BUFFER_SIZE = 8192

private
val HEX_DIGITS_UPPER =
    charArrayOf('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F')

private
val HEX_DIGITS_LOWER =
    charArrayOf('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f')

/**
 * 获取byte数组的MD5加密
 */
private fun ByteArray?.hashTemplate(algorithm: String = "MD5"): ByteArray? {
    if (this == null || this.isEmpty()) {
        return null
    }
    try {
        val md = MessageDigest.getInstance(algorithm)
        md.update(this)
        return md.digest()
    } catch (e: Exception) {
        e.printStackTrace()
        return null
    }
}

/**
 * 获取byte数组的MD5加密
 */
@JvmOverloads
fun ByteArray?.generateMd5(salt: ByteArray? = null, algorithm: String = "MD5"): ByteArray? {
    if (salt == null) {
        return hashTemplate(algorithm)
    }
    if (this == null) {
        return salt.hashTemplate(algorithm)
    }
    val dataSalt = ByteArray(size + salt.size)
    System.arraycopy(this, 0, dataSalt, 0, size)
    System.arraycopy(salt, 0, dataSalt, size, salt.size)
    return dataSalt.hashTemplate(algorithm)
}

/**
 * 获取byte数组的MD5加密字符串
 */
@JvmOverloads
fun ByteArray?.generateMd5String(salt: ByteArray? = null, algorithm: String = "MD5"): String? {
    return generateMd5(salt, algorithm)?.hexString()
}

/**
 * 获取byte数组的SHA1加密
 */
fun ByteArray?.encryptSHA1(): ByteArray? {
    return hashTemplate("SHA-1")
}

/**
 * 获取byte数组的SHA1加密字符串
 */
fun ByteArray?.encryptSHA1String(): String? {
    return encryptSHA1()?.hexString()
}

/**
 * 获取byte数组的SHA224加密
 */
fun ByteArray?.encryptSHA224(): ByteArray? {
    return hashTemplate("SHA224")
}

/**
 * 获取byte数组的SHA224加密字符串
 */
fun ByteArray?.encryptSHA224String(): String? {
    return encryptSHA224()?.hexString()
}

/**
 * 获取byte数组的SHA256加密
 */
fun ByteArray?.encryptSHA256(): ByteArray? {
    return hashTemplate("SHA-256")
}

/**
 * 获取byte数组的SHA256加密字符串
 */
fun ByteArray?.encryptSHA256String(): String? {
    return encryptSHA256()?.hexString()
}

/**
 * 获取byte数组的SHA384加密
 */
fun ByteArray?.encryptSHA384(): ByteArray? {
    return hashTemplate("SHA-384")
}

/**
 * 获取byte数组的SHA384加密字符串
 */
fun ByteArray?.encryptSHA384String(): String? {
    return encryptSHA384()?.hexString()
}

/**
 * 获取byte数组的SHA512加密
 */
fun ByteArray?.encryptSHA512(): ByteArray? {
    return hashTemplate("SHA-512")
}

/**
 * 获取byte数组的SHA512加密字符串
 */
fun ByteArray?.encryptSHA512String(): String? {
    return encryptSHA512()?.hexString()
}

/**
 * 获取byte数组的hex值
 */
@JvmOverloads
fun ByteArray?.hexString(isUpperCase: Boolean = true): String? {
    if (this == null || this.isEmpty()) {
        return null
    }
    val hexDigits =
        if (isUpperCase) HEX_DIGITS_UPPER else HEX_DIGITS_LOWER
    val len: Int = size
    if (len <= 0) return null
    val ret = CharArray(len shl 1)
    var i = 0
    var j = 0
    while (i < len) {
        ret[j++] = hexDigits[get(i).toInt() shr 4 and 0x0f]
        ret[j++] = hexDigits[get(i).toInt() and 0x0f]
        i++
    }
    return ret.concatToString()
}
